package anveshitha.indexers;

import static anveshitha.config.AnveshithaConstants.JAVA;
import static anveshitha.config.AnveshithaConstants.indexCounter;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Iterator;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.ws.jaxme.js.JavaMethod;
import org.apache.ws.jaxme.js.JavaQName;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.JavaSourceFactory;
import org.apache.ws.jaxme.js.util.JavaParser;

import anveshitha.analyzers.JavaSourceCodeAnalyzer;
import anveshitha.config.AnveshithaConstants.FieldEnum;


/**
 * This class indexes Java Source Files
 * @author varun
 */
public class JavaSourceCodeIndexer extends SourceCodeIndexer {

	public JavaSourceCodeIndexer(String sSrcDir, boolean recursive) {

		super(JAVA, sSrcDir, recursive, new JavaSourceCodeAnalyzer());
	}

	@Override
	public void indexFile(IndexWriter indexWriter, File file) throws Exception {
		Document luceneDoc = new Document();

		JavaSourceFactory javaSourceFactory = new JavaSourceFactory();
		JavaParser javaParser = new JavaParser(javaSourceFactory);
		javaParser.parse(file);

		// iterate through the sources in the file and index them
		for (Iterator iter = javaSourceFactory.getJavaSources(); iter.hasNext();) {
			JavaSource javaSource = (JavaSource) iter.next();

			// -----------INDEXING RULES----------
			// Field Type
			// ----------------------------------
			// Class Name Text (Stored,Tokenized)
			// Import Declarations Keyword (Stored,Indexed)
			// Method Name Text
			// Method Block (Code) UnStored (Not Stored, Tokenized)
			// File Name UnIndexed (Stored, Not Indexed)
			// Method Parameter Type Text
			// Return Type Text
			// Comments UnStored
			// Extends Class Text
			// Implements Text
			// Package Name UnIndexed
			// File Path UnIndexed

			luceneDoc.add(new Field(FieldEnum.FILENAME.name(), file.getName(), Field.Store.YES,
					Field.Index.NO));
			luceneDoc.add(new Field(FieldEnum.FILEPATH.name(), file.getAbsolutePath(), Field.Store.YES,
					Field.Index.NO));
			luceneDoc.add(new Field(FieldEnum.PACKAGENAME.name(), javaSource.getPackageName(), Field.Store.YES,
					Field.Index.UN_TOKENIZED));

			//TODO: Imports not being parsed
//			JavaQName[] javaQNames = javaSource.getImports();
//			for (JavaQName name : javaQNames) {
//				luceneDoc.add(new Field(FieldEnum.IMPORT.name(), name
//								.getClassName(), Field.Store.YES,
//								Field.Index.TOKENIZED));
//			}

			luceneDoc.add(new Field(FieldEnum.CLASSNAME.name(), javaSource
					.getClassName(), Field.Store.YES, Field.Index.TOKENIZED));

			addTextFields(luceneDoc, FieldEnum.EXTENDS, javaSource.getExtends());
			addTextFields(luceneDoc, FieldEnum.IMPLEMENTS, javaSource
					.getImplements());
			addMethodFields(luceneDoc, javaSource.getMethods());

			// TODO: Index Comments
//			JavaComment comment = javaSource.getComment();
//			if(comment != null)
//			{
//				luceneDoc.add(new Field(FieldEnum.COMMENTS.name(), comment.getLines()
//					.toString(), Field.Store.NO, Field.Index.TOKENIZED));
//			}		
			

		}

		indexWriter.addDocument(luceneDoc);
	}

	private static void addMethodFields(Document luceneDoc,
			JavaMethod[] javaMethods) {
		JavaQName[] javaQNames;
		for (JavaMethod method : javaMethods) {
			luceneDoc.add(new Field(FieldEnum.METHODNAME.name(), method
					.getName(), Field.Store.YES, Field.Index.TOKENIZED));

			// TODO: Index Method Code
//			luceneDoc.add(new Field(FieldEnum.METHODCODE.name(), Arrays.toString(method.getLines(0)),
//						Field.Store.YES, Field.Index.TOKENIZED));

			luceneDoc.add(new Field(FieldEnum.RETURNTYPE.name(), method
					.getType().getClassName(), Field.Store.YES,
					Field.Index.TOKENIZED));

			javaQNames = method.getParamTypes();
			for (JavaQName name : javaQNames)
				luceneDoc.add(new Field(FieldEnum.METHODPARAMTYPE.name(), name
								.getClassName(), Field.Store.YES,
								Field.Index.TOKENIZED));
		}
	}

	private static void addTextFields(Document luceneDoc, FieldEnum fieldType,
			JavaQName[] javaQNames) {
		for (JavaQName name : javaQNames)
			luceneDoc.add(new Field(fieldType.name(), name.getClassName(),
					Field.Store.YES, Field.Index.TOKENIZED));

	}

	/**
	 * Use for testing purposes
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		JavaSourceCodeIndexer jsi = new JavaSourceCodeIndexer(
				"/home/varun/workspace/anveshitha", true);
		System.out.println("Starting indexing....");
		long start = System.currentTimeMillis();
		try {
			jsi.index();
		} catch (FileNotFoundException e) {
			System.err.println(e.getMessage());
		}
		long end = System.currentTimeMillis();
		System.out.println("Done indexing of " + indexCounter + " files in ~"
				+ ((end - start) / 1000F) + " sec");
	}

}
